// praxis/services/sensor_manager.cc
#include "praxis/services/sensor_manager.h"

#include "praxis/hardware/simulated_sensor.h"

namespace praxis {
struct CSensorManager::Impl {
  std::unordered_map<std::string, std::shared_ptr<ISensor>> sensors;
  std::unordered_map<std::string, nlohmann::json> sensor_configs;
  nlohmann::json current_values_json;

  void CreateFromConfig(const nlohmann::json& config);
};

void CSensorManager::Impl::CreateFromConfig(const nlohmann::json& config) {
  if (!config.is_array()) return;
  for (const auto& sen_config : config) {
    auto sensor = std::make_shared<CSimulatedSensor>(
        sen_config.value("name", ""), sen_config.value("unit", ""),
        sen_config.value("initial_value", 0.0),
        sen_config.value("noise_amplitude", 0.1));

    sensors[sensor->GetName()] = sensor;
    sensor_configs[sensor->GetName()] = sen_config;
  }
}

CSensorManager::CSensorManager(const nlohmann::json& config)
    : impl_(std::make_unique<Impl>()) {
  impl_->CreateFromConfig(config);
}

CSensorManager::~CSensorManager() = default;

std::shared_ptr<ISensor> CSensorManager::GetSensor(const std::string& name) {
  auto it = impl_->sensors.find(name);
  return (it != impl_->sensors.end()) ? it->second : nullptr;
}

const std::unordered_map<std::string, std::shared_ptr<ISensor>>&
CSensorManager::GetAllSensors() const {
  return impl_->sensors;
}

const nlohmann::json& CSensorManager::GetSensorConfig(
    const std::string& name) const {
  static const nlohmann::json empty_json = {};
  auto it = impl_->sensor_configs.find(name);
  return (it != impl_->sensor_configs.end()) ? it->second : empty_json;
}

void CSensorManager::UpdateAllSensors() {
  for (auto const& [name, sensor] : impl_->sensors) {
    sensor->Update();
  }
}

const nlohmann::json& CSensorManager::GetCurrentValues() {
  impl_->current_values_json.clear();
  for (auto const& [name, sensor] : impl_->sensors) {
    impl_->current_values_json[name] = sensor->GetValueAsJson();
  }
  return impl_->current_values_json;
}
}  // namespace praxis